/**
 * PluginList.java 2008-05-16
 *        
 * Linker is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package linker.plugin;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Set;

import javax.swing.JPopupMenu;

import linker.LocalVariablesManager;
import linker.account.Account;
import linker.account.ManageAccount;
import linker.list.ListItem;
import linker.list.Listmodel;

/**
 * The list of plugin.It is a list model which is viewed in Linker as plugin
 * list.When it is initialing, it reader .class file from 'resources/plugins'
 * directroy,after initial it the plugin will be added to the list.
 * 
 * @version 2008-05-16
 * @author Jianfeng tujf.cn@gmail.com
 * 
 */

public class PluginList extends Listmodel {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * The list of pluginItem.
	 */
	private ArrayList<PluginItem> list = new ArrayList<PluginItem>();

	/**
	 * The saved refelter string.
	 */
	private String last = "";

	/**
	 * The plugins' properties.
	 */
	private Properties plugins = new Properties();

	/**
	 * The names of plugins.
	 */
	private Set<String> pluginNames;

	/**
	 * The path of plugin info.
	 */
	private String pluginInfoPath;

	/**
	 * 
	 * @throws IOException
	 *             The exception of file read.
	 */
	public PluginList() throws IOException {
		String path = ManageAccount.getConfigPath();
		String user = Account.getUser();

		pluginInfoPath = path + user + ".plugins";
		try {
			plugins.load(new InputStreamReader(new FileInputStream(
					pluginInfoPath), "UTF-8"));
		} catch (FileNotFoundException e) {
			plugins.store(new FileOutputStream(pluginInfoPath), "Plugins");
		}
		pluginNames = plugins.stringPropertyNames();

		refilter(null);
	}

	/**
	 * Double click event by the given list Item.
	 * 
	 * @param item
	 *            The double clicked list item.
	 */
	public final void doubleClickByItem(final ListItem item) {
		item.doubleClick();
	}

	/**
	 * Get popupMenu.
	 * 
	 * @param listItem
	 *            The doubleClicked listItem.
	 * @return The popupMenu.
	 */
	public final JPopupMenu getPopupMenuByItem(final ListItem listItem) {
		return null;
	}

	/**
	 * Get plugin properties.
	 * 
	 * @return The plugins' properties.
	 */
	public final Properties getPluginProperties() {
		return plugins;
	}

	/**
	 * Save the plugin properties.
	 * 
	 * @param properties
	 *            The Plugins's properties.
	 */
	public final void savePluginProperties(final Properties properties) {
		pluginNames = properties.stringPropertyNames();
		try {
			properties.store(new FileOutputStream(pluginInfoPath), "Plugins");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Load your local plugins.
	 * 
	 */
	public final void loadPlugins() {
		String pluginPath = ManageAccount.getPluginPath();
		File pluginDir = new File(pluginPath);

		final String disableValue = LocalVariablesManager
				.getLocalVariables("PluginWindow.TableModel.DisableValue");
		final String enableValue = LocalVariablesManager
				.getLocalVariables("PluginWindow.TableModel.EnableValue");

		if (pluginDir.exists()) {
			File[] files = pluginDir.listFiles();

			for (int t = 0; t < files.length; t++) {
				final File file = files[t];

				// To skip other file and hidden file.
				if (!file.isDirectory() || file.getName().charAt(0) == '.') {
					continue;
				}

				String classPath = file.getAbsolutePath() + File.separator
						+ file.getName() + ".class";
				File pluginToCheckExistence = new File(classPath);

				if (!pluginToCheckExistence.exists()) {
					// If the plugin doesn't exist it will be romoved from the
					// list and will disappear the next time you start the
					// application
					// It works only when the .class file doesn't exist but
					// the directory still exist.
					plugins.remove(file.getName());
					continue;
				} else {
					// If the plugin does exist but is not included in the list
					// this will add it to the list and set it disabled
					if (!pluginNames.contains(file.getName())) {
						plugins.put(file.getName(), disableValue);
						savePluginProperties(plugins);
						continue;
					}
				}

				// If the plugin has been disabled it won't be loaded
				if (((String) plugins.get(file.getName()))
						.startsWith(disableValue)) {
					continue;
				} else if (!((String) plugins.get(file.getName()))
						.startsWith(enableValue)) {
					// this will work when you change languages
					// set all unresloved plugins to be disabled
					plugins.setProperty(file.getName(), disableValue);
					continue;
				}

				// Create the proxy of pluginItem.
				PluginItem item = new PluginItem(file);
				list.add(item);
			}
		}
		// If the plugin aprears in the config file but the
		// direction of the plugin disappeared this will handdle it;
		for (String name : pluginNames) {
			String classPath = pluginPath + name.toString() + File.separator
					+ name.toString() + ".class";
			File pluginToCheckExistence = new File(classPath);
			if (!pluginToCheckExistence.exists()) {
				plugins.remove(name.toString());
			}
		}

		savePluginProperties(plugins);
		refilter(null);
	}

	/**
	 * Refilter the items displayed in the list.
	 * 
	 * @param s
	 *            The refilte string.
	 */
	public final void refilter(final String s) {

		if (s != null) {
			last = s;
		}

		PluginItem listItem;
		clear();

		for (int i = 0; i < list.size(); i++) {
			listItem = list.get(i);

			if (listItem.toString().indexOf(last) >= 0) {
				addElement(listItem);
			}
		}
	}

}
